﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using thinger.DataConvertLib;


namespace PLC
{
    public partial class Form1 : Form
    {

        
        public Form1()
        {
            InitializeComponent();
        }


        //创建一个socket对象

        private Socket tcpClient;


        //多线程

        private CancellationTokenSource cts;


        private const int ReceiveCount = 200;
        private const int SendCount = 100;
        private byte[] receive;
        private static readonly object objLock= new object();
        private void groupBox2_Enter(object sender, EventArgs e)
        {

        }

        private void label14_Click(object sender, EventArgs e)
        {

        }

        private void btn_Connect_Click(object sender, EventArgs e)
        {
            tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
           
            try
            {
                tcpClient.Connect(IPAddress.Parse(this.text_Ip.Text), int.Parse(this.text_Port.Text));

            }
            catch (Exception ex)
            {

                MessageBox.Show("PLC连接失败" + ex.Message,"建立连接");
            return;
            }

            MessageBox.Show("PLC连接成功" );
            cts=new CancellationTokenSource();

            Task.Run(new Action(() =>
                {

                    ReceiveFromPlc();

                }

                ),cts.Token);



        }

        private void ReceiveFromPlc()
        {

            while (!cts.IsCancellationRequested)
            {
                //  定义个缓冲区
                byte[] buffer = new byte[1024];

                    //实际接收的长度
                    int length = -1;

                try
                {

                   length= tcpClient.Receive(buffer, SocketFlags.None);
                }

                catch (Exception)
                {
                    //日志
                    break;
                
                }
                if (length == ReceiveCount)
                {
                    //数据解析及显示
                    ReceiveAndUpdate(buffer);
                
                }

            }

        }

        private void btn_Disconnect_Click(object sender, EventArgs e)
        {
            cts?.Cancel();
            tcpClient?.Close();
        }

        private void text_Ip_TextChanged(object sender, EventArgs e)
        {

        }

        private void text_Port_TextChanged(object sender, EventArgs e)
        {

        }

        private void ReceiveAndUpdate(byte[] buffer)
        {

            //获取需要的字节数
            byte[] send = ByteArrayLib.GetByteArrayFromByteArray(buffer, 0,   ReceiveCount- SendCount);

             receive = ByteArrayLib.GetByteArrayFromByteArray(buffer, ReceiveCount - SendCount, SendCount);

            this.Invoke(new Action(() =>

            {
                foreach (var item in this.gp_Read.Controls)
                {

                    if (item is Label label)
                    {

                        if (label.Tag != null && label.Tag.ToString().Length > 0)

                        {

                            var tagResult = GetBindVariableFromTag(label.Tag.ToString());

                            if (tagResult.IsSuccess)
                            {
                                var bindVarlable = tagResult.Content;
                                switch (bindVarlable.DataType)
                                {

                                    case DataType.Bool:
                                        label.BackColor = BitLib.GetBitFromByteArray(
                                        send, bindVarlable.Start, bindVarlable.OffsetOrLength) ? Color.LimeGreen : Color.Red;


                                        break;
                                    case DataType.Byte:
                                        label.Text = ByteLib.GetByteFromByteArray(
                                      send, bindVarlable.Start).ToString();



                                        break;

                                    case DataType.Short:

                                        label.Text = ShortLib.GetShortFromByteArray(
                                      send, bindVarlable.Start).ToString();


                                        break;
                                    case DataType.UShort:

                                        label.Text = UShortLib.GetUShortFromByteArray(
                                     send, bindVarlable.Start).ToString();


                                        break;
                                    case DataType.Int:

                                        label.Text = IntLib.GetIntFromByteArray(
                                     send, bindVarlable.Start).ToString();


                                        break;

                                    case DataType.UInt:

                                        label.Text = UIntLib.GetUIntFromByteArray(
                                     send, bindVarlable.Start).ToString();

                                        break;
                                    case DataType.Float:
                                        label.Text = FloatLib.GetFloatFromByteArray(
                                    send, bindVarlable.Start).ToString();


                                        break;
                                    case DataType.Double:

                                        label.Text = DoubleLib.GetDoubleFromByteArray(
                                    send, bindVarlable.Start).ToString();

                                        break;
                                    case DataType.Long:

                                        label.Text = LongLib.GetLongFromByteArray(
                                   send, bindVarlable.Start).ToString();

                                        break;
                                    case DataType.ULong:
                                        label.Text = ULongLib.GetULongFromByteArray(send, bindVarlable.Start).ToString();
                                        break;
                                  
                                    default:
                                        break;


                                }
                            }
                            else
                            {
                            }

                        }

                    }



                }

                foreach (var item in this.gp_Write.Controls)
                {

                    if (item is Label label)
                    {

                        if (label.Tag != null && label.Tag.ToString().Length > 0)

                        {

                            var tagResult = GetBindVariableFromTag(label.Tag.ToString());

                            if (tagResult.IsSuccess)
                            {
                                var bindVarlable = tagResult.Content;
                                switch (bindVarlable.DataType)
                                {

                                    case DataType.Bool:
                                        label.BackColor = BitLib.GetBitFromByteArray(
                                        receive, bindVarlable.Start, bindVarlable.OffsetOrLength) ? Color.LimeGreen : Color.Red;


                                        break;
                                    case DataType.Byte:
                                        label.Text = ByteLib.GetByteFromByteArray(
                                      receive, bindVarlable.Start).ToString();

                                        break;
                                    case DataType.Short:
                                        label.Text = ShortLib.GetShortFromByteArray(receive, bindVarlable.Start).ToString();
                                        break;
                                    case DataType.UShort:
                                        label.Text = UShortLib.GetUShortFromByteArray(receive, bindVarlable.Start).ToString();
                                        break;
                                    case DataType.Int:
                                        label.Text = IntLib.GetIntFromByteArray(receive, bindVarlable.Start).ToString();
                                        break;
                                    case DataType.UInt:
                                        label.Text = UIntLib.GetUIntFromByteArray(receive, bindVarlable.Start).ToString();
                                        break;
                                    case DataType.Float:
                                        label.Text = FloatLib.GetFloatFromByteArray(receive, bindVarlable.Start).ToString();
                                        break;
                                    case DataType.Double:
                                        label.Text = DoubleLib.GetDoubleFromByteArray(receive, bindVarlable.Start).ToString();
                                        break;
                                    case DataType.Long:
                                        label.Text = LongLib.GetLongFromByteArray(receive, bindVarlable.Start).ToString();
                                        break;
                                    case DataType.ULong:
                                        label.Text = ULongLib.GetULongFromByteArray(receive, bindVarlable.Start).ToString();
                                        break;
                                  
                                    default:
                                        break;


                                }
                            }
                            else
                            {
                                //写日志
                            }

                        }

                    }



                }
            }
            
            
            
            ));


            //数据就拿到了




        }

        /// <summary>
        /// 将Tag的值转换成一个对象
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>

        private OperateResult<BindVariable> GetBindVariableFromTag(string tag)
        {
            // tag是否包含逗号
            if (tag.Contains(","))
            {
            string[] info= tag.Split(',');

                if (info.Length == 2)
                {

                    try
                        {

                        BindVariable bindVariable = new BindVariable();

                       bindVariable. DataType = (DataType)Convert.ToInt32(info[1]);

                        if (info[0].Contains("."))
                        {
                            string[] str = info[0].Split('.');
                            if (str.Length == 2)
                            {
                                bindVariable.Start = Convert.ToInt32(str[0]);
                                bindVariable.OffsetOrLength = Convert.ToInt32(str[1]);
                                return OperateResult.CreateSuccessResult(bindVariable);
                            }
                            else {
                                return OperateResult.CreateFailResult<BindVariable>("绑定的Tag格式不正确" + tag);
                            }
                        
                        
                        }
                        else
                        {
                            bindVariable.Start = Convert.ToInt32(info[0]);
                            bindVariable.OffsetOrLength = 0;
                            return OperateResult.CreateFailResult<BindVariable>("绑定的Tag格式不正确" + tag);

                        }



                    }
                    catch (Exception ex)
                    {
                        return OperateResult.CreateFailResult<BindVariable>("绑定的Tag格式不正确" + tag);

                    }
               
                
                }
                else
                {
                    return OperateResult.CreateFailResult<BindVariable>("绑定的Tag格式不正确" + tag);

                }




            
            }
            else {
                return OperateResult.CreateFailResult<BindVariable>("绑定的Tag格式不正确"+tag);
            
            }
        
        
        }


    }
}
